package top.wshape1.shiziapi.message.service.impl;

import com.alibaba.fastjson2.JSON;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import top.wshape1.shiziapi.common.constant.RedisConstant;
import top.wshape1.shiziapi.common.domain.vo.MessageVo;
import top.wshape1.shiziapi.message.config.RabbitMqConfig;
import top.wshape1.shiziapi.message.service.WebSocketService;
import top.wshape1.shiziapi.message.websocket.WsSessionManager;

import java.io.IOException;

/**
 * @author Wshape1
 * @version 1.0
 * @description
 * @since 2024-01-24
 */

@Service
@Slf4j
public class WebSocketServiceImpl implements WebSocketService {

    @Resource
    private WsSessionManager sessionManager;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void sendMessage(Long userId, MessageVo messageVo) {
        // 如果在线才发送
        if (sessionManager.isOnline(userId.toString())) {
            WebSocketSession session = sessionManager.get(userId.toString());

            if (session != null) {
                // ！=null说明该session在这台服务节点上
                TextMessage textMessage = new TextMessage(JSON.toJSONString(messageVo));
                try {
                    session.sendMessage(textMessage);
                } catch (IOException e) {
                    log.error("发送消息失败，error -> ", e);
                }
            } else {
                // ==null说明不在这台服务节点上，需要通过RabbitMQ广播给其它服务节点

                Object nodeID = redisTemplate.opsForValue().get(RedisConstant.WEBSOCKET_USER_NODE_KEY + userId);
                if (nodeID != null && StringUtils.hasText((String) nodeID)) {
                    // 存在该用户对应WebSocket的缓存，直接发送到对应的节点
                    rabbitTemplate.convertAndSend(RabbitMqConfig.SHIZIAPI_MESSAGE_USER_EXCHANGE,
                            RabbitMqConfig.SHIZIAPI_MESSAGE_USER_BINDING_PREFIX + nodeID, messageVo);
                } else {
                    // 不存在该用户对应WebSocket的缓存，广播给所有节点
                    rabbitTemplate.convertAndSend(RabbitMqConfig.SHIZIAPI_MESSAGE_BROADCAST_EXCHANGE,
                            RabbitMqConfig.SHIZIAPI_MESSAGE_USER_BINDING_PREFIX + "*", messageVo);
                }
            }
        }
    }

    @Override
    public void sendBroadcastMessage(MessageVo data) {
        rabbitTemplate.convertAndSend(RabbitMqConfig.SHIZIAPI_MESSAGE_BROADCAST_EXCHANGE,
                "", data);
    }
}
